home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 23
/
AACD 23.iso
/
AACD
/
Online
/
opennap
/
server_links.c
< prev
next >
Wrap
C/C++ Source or Header
|
2001-06-08
|
7KB
|
296 lines
/* Copyright (C) 2000 edwards@bitchx.dimension6.com
This is free software distributed under the terms of the
GNU Public License. See the file COPYING for details.
Modified by drscholl@users.sourceforge.net 2/25/2000.
$Id: server_links.c,v 1.28 2001/01/08 10:15:15 drscholl Exp $ */
#include <string.h>
#if !defined( WIN32) || defined(__CYGWIN__)
#include <sys/time.h>
#include <unistd.h>
#else
#include <time.h>
#endif
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include <stdio.h>
#include <ctype.h>
#include "opennap.h"
#include "debug.h"
#if defined( WIN32) && !defined(__CYGWIN__)
/* emulate gettimeofday, only uses seconds since I can't figure out how
* to get sub-second accurracy
*/
static int
gettimeofday (struct timeval *ptr, void *unused)
{
memset (ptr, 0, sizeof (struct timeval));
ptr->tv_sec = time (0);
return 0;
}
#endif
/* 10112 */
/* process client request for server links */
HANDLER (server_links)
{
LIST *list;
LINK *slink;
CONNECTION *serv;
(void) tag;
(void) len;
(void) pkt;
CHECK_USER_CLASS ("server_links");
ASSERT (validate_connection (con));
/* first dump directly connected servers */
for (list = Servers; list; list = list->next)
{
serv = list->data;
send_cmd (con, MSG_SERVER_LINKS, "%s %hu %s %hu 1",
Server_Name, get_local_port (serv->fd), serv->host,
serv->port);
}
/* dump remote servers */
for (list = Server_Links; list; list = list->next)
{
slink = list->data;
send_cmd (con, MSG_SERVER_LINKS, "%s %hu %s %hu %d", slink->server,
slink->port, slink->peer, slink->peerport, slink->hops);
}
/* terminate the list */
send_cmd (con, MSG_SERVER_LINKS, "");
}
/* 750 [ :<sender> ] <server> [args] */
HANDLER (ping_server)
{
USER *sender;
char *recip;
char *sender_name;
(void) len;
ASSERT (validate_connection (con));
if (pop_user_server (con, tag, &pkt, &sender_name, &sender))
return;
recip = next_arg (&pkt);
if (!recip || !strcasecmp (Server_Name, recip))
{
/* local server is being pinged */
if (ISUSER (con))
/* local user issued request */
send_cmd (con, tag, "%s %s", Server_Name, NONULL (pkt));
else
/* use inter-server pong message to reply */
send_cmd (con, MSG_SERVER_SERVER_PONG,
":%s %s %s", Server_Name, sender_name, NONULL (pkt));
}
else if (is_server (recip))
{
/* client request from remote server to remote server */
pass_message_args (con, tag, ":%s %s %s", sender_name, recip,
NONULL (pkt));
}
else if (ISUSER (con))
send_cmd (con, MSG_SERVER_NOSUCH,
"server ping failed: no such server");
else
log
("ping_server: recv'd ping for unknown server %s from server %s (originated from %s)",
recip, con->host, sender_name);
}
/* 10022 :<server> <recip> [args]
* server->server pong response
*/
HANDLER (server_pong)
{
char *server;
char *nick;
USER *user;
CHECK_SERVER_CLASS ("server_pong");
(void) len;
server = next_arg (&pkt);
nick = next_arg (&pkt);
if (!server || !nick)
{
log ("server_pong: error, missing argument(s)");
return;
}
server++; /* skip the colon */
user = hash_lookup (Users, nick);
if (user)
{
if (ISUSER (user->con))
/* user is local, deliver the response */
send_cmd (user->con, MSG_CLIENT_PING_SERVER, "%s %s",
server, NONULL (pkt));
else
/* route directly to the server that the user is behind */
send_cmd (user->con, tag, ":%s %s %s",
server, user->nick, NONULL (pkt));
}
/* recip is not a user, check to see if it's the local server */
else if (!strcasecmp (Server_Name, nick))
{
char *secs;
char *usecs;
/* response is for the local server. do lag checking */
secs = next_arg (&pkt);
usecs = next_arg (&pkt);
if (secs && usecs)
{
struct timeval tv;
gettimeofday (&tv, NULL);
notify_mods (PINGLOG_MODE, "Pong from server %s [%d millisecs]",
server,
(int) ((((tv.tv_sec - atoi (secs)) * 1000000. +
tv.tv_usec - atoi (usecs)) / 1000000.) * 1000.));
}
else
log ("server_pong: pong from %s with invalid args", con->host);
}
else if (is_server (nick))
pass_message_args (con, tag, ":%s %s %s", server, nick, NONULL (pkt));
else
log ("server_pong: unknown target %s from server %s", nick,
con->host);
}
/* this currently doesn't do anything more than ping the peer servers and
* report the lag times to mods+
*/
void
lag_detect (void *p)
{
LIST *list;
CONNECTION *con;
struct timeval tv;
(void) p; /* unused */
if (Servers)
{
gettimeofday (&tv, 0);
/* ping all of our peer servers */
for (list = Servers; list; list = list->next)
{
con = list->data;
send_cmd (con, MSG_CLIENT_PING_SERVER, ":%s %s %u %u",
Server_Name, con->host, tv.tv_sec, tv.tv_usec);
}
notify_mods (PINGLOG_MODE, "Pinging all peer servers...");
}
}
/* 10120
* ping all peer servers
*/
HANDLER (ping_all_servers)
{
(void) tag;
(void) len;
(void) pkt;
CHECK_USER_CLASS ("ping_all_servers");
if (con->user->level < LEVEL_MODERATOR)
{
send_cmd (con, MSG_SERVER_NOSUCH,
"ping all servers failed: permission denied");
return;
}
lag_detect (0);
}
void
free_server_auth (server_auth_t * auth)
{
FREE (auth->name);
if (auth->alias)
FREE (auth->alias);
FREE (auth->their_pass);
FREE (auth->my_pass);
FREE (auth);
}
void
load_server_auth (void)
{
char path[_POSIX_PATH_MAX];
FILE *fp;
int ac;
char *av[10];
int line = 0;
server_auth_t *slink;
LIST *list;
list_free (Server_Auth, (list_destroy_t) free_server_auth);
Server_Auth = 0;
snprintf (path, sizeof (path), "%s/servers", Config_Dir);
fp = fopen (path, "r");
if (!fp)
{
if (errno != ENOENT)
logerr ("load_server_auth_info", path);
return;
}
log ("load_server_auth_info: reading %s", path);
Buf[sizeof (Buf) - 1] = 0;
while (fgets (Buf, sizeof (Buf) - 1, fp))
{
line++;
if (Buf[0] == '#' || isspace (Buf[0]))
continue;
ac = split_line (av, FIELDS (av), Buf);
if (ac >= 3)
{
slink = CALLOC (1, sizeof (server_auth_t));
slink->name = STRDUP (av[0]);
slink->their_pass = STRDUP (av[1]);
slink->my_pass = STRDUP (av[2]);
if (ac >= 4)
{
slink->port = atoi (av[3]);
if (slink->port < 1 || slink->port > 65535)
{
log ("load_server_auth_info: invalid port at line %d",
line);
slink->port = 8888;
}
/* if a nickname for the server is given, save it so that
* we can sheild the real dns name from the masses (used
* for routing-only servers which we want to make pratically
* invisible).
*/
if (ac >= 5)
slink->alias = STRDUP (av[4]);
}
else
slink->port = 8888;
list = CALLOC (1, sizeof (LIST));
list->data = slink;
list->next = Server_Auth;
Server_Auth = list;
}
else
log ("load_server_auth_info: too few parameters at line %d",
line);
}
fclose (fp);
}